{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import os\n",
    "import io\n",
    "import sys\n",
    "import json\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "import astropy.units as u\n",
    "from astropy import wcs\n",
    "from astropy.io import fits\n",
    "from astropy.table import Table\n",
    "from astropy.coordinates import SkyCoord\n",
    "from astropy.visualization import make_lupton_rgb\n",
    "from astropy.utils.data import download_file, clear_download_cache\n",
    "\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Query HSC database using SQL search\n",
    "\n",
    "* Here `unagi` provides the basic function to run quick SQL search of HSC database\n",
    "* If you need to run large `SQL` search (longer than ~10 mins), please use the `CAS` online search interface\n",
    "\n",
    "### Step 1: Setup HSC-SSP online data archive \n",
    "\n",
    "* First, you need to setup a HSC-SSP rerun\n",
    "* Here we use the wide field from the `PDR1` as an example\n",
    "* `SQL` search only cares about the data release (`dr`), you can use any `rerun` you want and still have access to all "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Get table list from /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_dud/pdr2_dud_tables.fits\n"
     ]
    }
   ],
   "source": [
    "from unagi import hsc\n",
    "from unagi import task\n",
    "from unagi import query\n",
    "from unagi import config\n",
    "from unagi import plotting\n",
    "\n",
    "pdr2 = hsc.Hsc(dr='pdr2', rerun='pdr2_dud')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic SQL search \n",
    "\n",
    "* You need to write your own `SQL` script and pass it to query\n",
    "* The output is a `astropy.table` table. It can be saved as an output file\n",
    "* By default\n",
    "    - We will skip the syntax check.  If you want syntax check, please set `skip_syntax=False`\n",
    "    - We will delete the search result from the database after the search is done. If you want to keep the data, please set `delete_after=False`\n",
    "    - We turn off the e-mail notification. If you don't mind being bothered by a lot of e-mails, set `noemail=False`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SELECT\n",
      "\tobject_id\n",
      "      , ra\n",
      "      , dec\n",
      "      , i_kronflux_mag\n",
      "      , i_kronflux_magsigma\n",
      "      , y_kronflux_mag\n",
      "      , y_kronflux_magsigma\n",
      "      , i_kronflux_mag - y_kronflux_mag AS i_y\n",
      "    FROM\n",
      "\tpdr2_dud.forced\n",
      "\tJOIN pdr2_dud.forced2 USING (object_id)\n",
      "    WHERE\n",
      "\t  boxSearch(coord, 34.0, 36.0, -5.0, -4.5)\n",
      "          /* is equivalent to\n",
      "                 ra  BETWEEN 34.0 AND 36.0\n",
      "             AND dec BETWEEN -5.0 AND -4.5\n",
      "             but boxSearch() is much faster\n",
      "          */\n",
      "\tAND i_kronflux_mag < 25.5\n",
      "    LIMIT 10\n",
      ";\n"
     ]
    }
   ],
   "source": [
    "sql_test = open('../unagi/test/test_query_1.sql', 'r').read()\n",
    "print(sql_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Waiting for query to finish... [Done]\n",
      "    object_id             ra         ... y_kronflux_magsigma     i_y     \n",
      "----------------- ------------------ ... ------------------- ------------\n",
      "37484992795778534   34.4252353277551 ...          0.69099116   -0.6347904\n",
      "37484992795811564  34.42407255027225 ...          0.16868027    1.5192337\n",
      "37484992795812411  34.42568076337248 ...          0.11366094 -0.017801285\n",
      "37484992795777926 34.425482291797934 ...          0.16416766   0.22124672\n",
      "37484992795778758  34.42466103010599 ...           2.4685438   -1.4152412\n",
      "37484992795778814  34.42460507919375 ...          0.19626102   0.57837486\n",
      "37484992795779204  34.42417359236723 ...       0.00078149483    0.7457905\n",
      "37484992795779508  34.42358230368066 ...         0.038728382   0.93774414\n",
      "37484992795805184  34.42819665647677 ...         0.036202993   0.41768646\n",
      "37484992795805232  34.42844265271551 ...            0.685199   -0.3396778\n"
     ]
    }
   ],
   "source": [
    "sql_file = '../unagi/test/test_query_1.sql'\n",
    "result_test = pdr2.sql_query(sql_file, from_file=True, verbose=True)\n",
    "\n",
    "print(result_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Preview a large SQL search\n",
    "\n",
    "* You can also test certain `SQL` search using the `preview=True` option. It will return the first 10 objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Preview the SQL search result...\n",
      "['object_id', 'ra', 'dec', 'i_kronflux_mag', 'i_kronflux_magsigma', 'y_kronflux_mag', 'y_kronflux_magsigma', 'i_y']\n",
      "['37484992795778534', '34.4252353277550966', '-4.60755454931688746', '25.3793411', '0.0927133486', '26.0141315', '0.690991163', '-0.634790421']\n",
      "['37484992795811564', '34.4240725502722498', '-4.58851214394431128', '25.4374199', '0.175520271', '23.9181862', '0.168680266', '1.5192337']\n",
      "['37484992795812411', '34.4256807633724833', '-4.60325464193815126', '23.4733677', '0.0276754815', '23.491169', '0.113660939', '-0.0178012848']\n",
      "['37484992795777926', '34.425482291797934', '-4.61860434203913428', '25.3206272', '0.0488657616', '25.0993805', '0.164167657', '0.221246719']\n",
      "['37484992795778758', '34.4246610301059874', '-4.60347780104875071', '25.4203186', '0.161276862', '26.8355598', '2.46854377', '-1.41524124']\n",
      "['37484992795778814', '34.4246050791937535', '-4.60248828142772481', '25.1134052', '0.0816069618', '24.5350304', '0.196261019', '0.578374863']\n",
      "['37484992795779204', '34.4241735923672323', '-4.59691150954412375', '19.7664509', '0.000419262418', '19.0206604', '0.000781494833', '0.745790482']\n",
      "['37484992795779508', '34.4235823036806607', '-4.58686570135185256', '23.398798', '0.0225712005', '22.4610538', '0.0387283824', '0.937744141']\n",
      "['37484992795805184', '34.4281966564767714', '-4.64735768920491576', '23.2961121', '0.0125801712', '22.8784256', '0.0362029932', '0.417686462']\n",
      "['37484992795805232', '34.4284426527155105', '-4.65159689979760138', '25.1125965', '0.119297467', '25.4522743', '0.685199022', '-0.339677811']\n"
     ]
    }
   ],
   "source": [
    "res = pdr2.sql_query(sql_test, preview=True, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Demo Search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Get table list from /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_dud/pdr2_dud_tables.fits\n",
      " [Done]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<i>Table length=10</i>\n",
       "<table id=\"table4375029456\" class=\"table-striped table-bordered table-condensed\">\n",
       "<thead><tr><th>object_id</th><th>ra</th><th>dec</th><th>i_kronflux_mag</th><th>i_kronflux_magsigma</th><th>y_kronflux_mag</th><th>y_kronflux_magsigma</th><th>i_y</th></tr></thead>\n",
       "<thead><tr><th>int64</th><th>float64</th><th>float64</th><th>float32</th><th>float32</th><th>float32</th><th>float32</th><th>float32</th></tr></thead>\n",
       "<tr><td>37484992795778534</td><td>34.4252353277551</td><td>-4.6075545493168875</td><td>25.379341</td><td>0.09271335</td><td>26.014132</td><td>0.69099116</td><td>-0.6347904</td></tr>\n",
       "<tr><td>37484992795811564</td><td>34.42407255027225</td><td>-4.588512143944311</td><td>25.43742</td><td>0.17552027</td><td>23.918186</td><td>0.16868027</td><td>1.5192337</td></tr>\n",
       "<tr><td>37484992795812411</td><td>34.42568076337248</td><td>-4.603254641938151</td><td>23.473368</td><td>0.027675482</td><td>23.491169</td><td>0.11366094</td><td>-0.017801285</td></tr>\n",
       "<tr><td>37484992795777926</td><td>34.425482291797934</td><td>-4.618604342039134</td><td>25.320627</td><td>0.04886576</td><td>25.09938</td><td>0.16416766</td><td>0.22124672</td></tr>\n",
       "<tr><td>37484992795778758</td><td>34.42466103010599</td><td>-4.603477801048751</td><td>25.420319</td><td>0.16127686</td><td>26.83556</td><td>2.4685438</td><td>-1.4152412</td></tr>\n",
       "<tr><td>37484992795778814</td><td>34.42460507919375</td><td>-4.602488281427725</td><td>25.113405</td><td>0.08160696</td><td>24.53503</td><td>0.19626102</td><td>0.57837486</td></tr>\n",
       "<tr><td>37484992795779204</td><td>34.42417359236723</td><td>-4.596911509544124</td><td>19.76645</td><td>0.00041926242</td><td>19.02066</td><td>0.00078149483</td><td>0.7457905</td></tr>\n",
       "<tr><td>37484992795779508</td><td>34.42358230368066</td><td>-4.586865701351853</td><td>23.398798</td><td>0.0225712</td><td>22.461054</td><td>0.038728382</td><td>0.93774414</td></tr>\n",
       "<tr><td>37484992795805184</td><td>34.42819665647677</td><td>-4.647357689204916</td><td>23.296112</td><td>0.012580171</td><td>22.878426</td><td>0.036202993</td><td>0.41768646</td></tr>\n",
       "<tr><td>37484992795805232</td><td>34.42844265271551</td><td>-4.651596899797601</td><td>25.112597</td><td>0.11929747</td><td>25.452274</td><td>0.685199</td><td>-0.3396778</td></tr>\n",
       "</table>"
      ],
      "text/plain": [
       "<Table length=10>\n",
       "    object_id             ra         ... y_kronflux_magsigma     i_y     \n",
       "      int64            float64       ...       float32         float32   \n",
       "----------------- ------------------ ... ------------------- ------------\n",
       "37484992795778534   34.4252353277551 ...          0.69099116   -0.6347904\n",
       "37484992795811564  34.42407255027225 ...          0.16868027    1.5192337\n",
       "37484992795812411  34.42568076337248 ...          0.11366094 -0.017801285\n",
       "37484992795777926 34.425482291797934 ...          0.16416766   0.22124672\n",
       "37484992795778758  34.42466103010599 ...           2.4685438   -1.4152412\n",
       "37484992795778814  34.42460507919375 ...          0.19626102   0.57837486\n",
       "37484992795779204  34.42417359236723 ...       0.00078149483    0.7457905\n",
       "37484992795779508  34.42358230368066 ...         0.038728382   0.93774414\n",
       "37484992795805184  34.42819665647677 ...         0.036202993   0.41768646\n",
       "37484992795805232  34.42844265271551 ...            0.685199   -0.3396778"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pdr2 = hsc.Hsc(dr='pdr2', rerun='pdr2_dud')\n",
    "\n",
    "# Simple example query\n",
    "sql_file = '../unagi/test/test_query_1.sql'\n",
    "# Result will be a astropy table\n",
    "pdr2.sql_query(sql_file, from_file=True, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### List all the tables in the rerun"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Read from saved file /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_dud/pdr2_dud_tables.fits\n",
      "['calibframe', 'calibframe_hpx11', 'calibframe_mng', 'fcr', 'fcr_mng', 'forced', 'forced2', 'forced3', 'forced4', 'forced5', 'frame', 'frame_hpx11', 'frame_mng', 'meas', 'meas2', 'meas3', 'meas4', 'mosaic', 'mosaic_hpx11', 'mosaic_mng', 'mosaicframe', 'patch_qa', 'random', 'smallcat', 'specz', 'warped', 'warped_hpx11', 'warped_mng', 'wcs', 'wcs_mng']\n"
     ]
    }
   ],
   "source": [
    "print(pdr2.tables(save=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get the schema of a table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Read from saved file /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_dud/pdr2_dud_forced_schema.fits\n"
     ]
    }
   ],
   "source": [
    "forced_schema = pdr2.table_schema('forced', save=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build a complete list of schema for all tables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Get table list from /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_wide/pdr2_wide_tables.fits\n"
     ]
    }
   ],
   "source": [
    "pdr2_wide = hsc.Hsc(dr='pdr2', rerun='pdr2_wide')\n",
    "\n",
    "pdr2_wide_schema = pdr2_wide.build_schema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Querying for the table list and save it to /Users/song/Dropbox/work/project/unagi/unagi/data/s18a_wide/s18a_wide_tables.fits\n",
      "# Dealing with 46 catalogs, this will take a while\n",
      "# Deal with table: calibframe\n",
      "# Deal with table: calibframe_anaresult\n",
      "# Deal with table: calibframe_hpx11\n",
      "# Deal with table: calibframe_mng\n",
      "# Deal with table: fcr\n",
      "# Deal with table: fcr_anaresult\n",
      "# Deal with table: fcr_mng\n",
      "# Deal with table: forced\n",
      "# Deal with table: forced2\n",
      "# Deal with table: forced3\n",
      "# Deal with table: forced4\n",
      "# Deal with table: forced5\n",
      "# Deal with table: frame\n",
      "# Deal with table: frame_anaresult\n",
      "# Deal with table: frame_hpx11\n",
      "# Deal with table: frame_mng\n",
      "# Deal with table: masks\n",
      "# Deal with table: masks_obsolate\n",
      "# Deal with table: meas\n",
      "# Deal with table: meas2\n",
      "# Deal with table: meas3\n",
      "# Deal with table: meas4\n",
      "# Deal with table: mosaic\n",
      "# Deal with table: mosaic_anaresult\n",
      "# Deal with table: mosaic_hpx11\n",
      "# Deal with table: mosaic_mng\n",
      "# Deal with table: mosaicframe\n",
      "# Deal with table: patch_qa\n",
      "# Deal with table: photoz_demp\n",
      "# Deal with table: photoz_demp_obsolate\n",
      "# Deal with table: photoz_mizuki\n",
      "# Deal with table: photoz_mizuki_obsolate\n",
      "# Deal with table: random\n",
      "# Deal with table: random_masks\n",
      "# Deal with table: random_masks_obsolate\n",
      "# Deal with table: smallcat\n",
      "# Deal with table: specz\n",
      "# Deal with table: testyy\n",
      "# Deal with table: tract_colorterm\n",
      "# Deal with table: warped\n",
      "# Deal with table: warped_anaresult\n",
      "# Deal with table: warped_hpx11\n",
      "# Deal with table: warped_mng\n",
      "# Deal with table: wcs\n",
      "# Deal with table: wcs_anaresult\n",
      "# Deal with table: wcs_mng\n",
      "# Querying for the table list and save it to /Users/song/Dropbox/work/project/unagi/unagi/data/s18a_dud/s18a_dud_tables.fits\n",
      "# Dealing with 42 catalogs, this will take a while\n",
      "# Deal with table: calibframe\n",
      "# Deal with table: calibframe_anaresult\n",
      "# Deal with table: calibframe_hpx11\n",
      "# Deal with table: calibframe_mng\n",
      "# Deal with table: fcr\n",
      "# Deal with table: fcr_anaresult\n",
      "# Deal with table: fcr_mng\n",
      "# Deal with table: forced\n",
      "# Deal with table: forced2\n",
      "# Deal with table: forced3\n",
      "# Deal with table: forced4\n",
      "# Deal with table: forced5\n",
      "# Deal with table: frame\n",
      "# Deal with table: frame_anaresult\n",
      "# Deal with table: frame_hpx11\n",
      "# Deal with table: frame_mng\n",
      "# Deal with table: masks\n",
      "# Deal with table: masks_obsolate\n",
      "# Deal with table: meas\n",
      "# Deal with table: meas2\n",
      "# Deal with table: meas3\n",
      "# Deal with table: meas4\n",
      "# Deal with table: mosaic\n",
      "# Deal with table: mosaic_anaresult\n",
      "# Deal with table: mosaic_hpx11\n",
      "# Deal with table: mosaic_mng\n",
      "# Deal with table: mosaicframe\n",
      "# Deal with table: patch_qa\n",
      "# Deal with table: photoz_demp\n",
      "# Deal with table: photoz_mizuki\n",
      "# Deal with table: random\n",
      "# Deal with table: random_masks\n",
      "# Deal with table: random_masks_obsolate\n",
      "# Deal with table: smallcat\n",
      "# Deal with table: specz\n",
      "# Deal with table: warped\n",
      "# Deal with table: warped_anaresult\n",
      "# Deal with table: warped_hpx11\n",
      "# Deal with table: warped_mng\n",
      "# Deal with table: wcs\n",
      "# Deal with table: wcs_anaresult\n",
      "# Deal with table: wcs_mng\n"
     ]
    }
   ],
   "source": [
    "s18a_wide = hsc.Hsc(dr='dr2', rerun='s18a_wide')\n",
    "s18a_wide_schema = s18a_wide.build_schema()\n",
    "\n",
    "s18a_dud = hsc.Hsc(dr='dr2', rerun='s18a_dud')\n",
    "s18a_dud_schema = s18a_dud.build_schema()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Check if a coordinate is covered by HSC \n",
    "\n",
    "* Use the `patch_contains` function of HSC archive to find which `Tract` and `Patch` covers a coordinate.\n",
    "* Unfortunately this is not fast, it takes a few seconds to search for one object.\n",
    "* And also, it only tells you that the coordinate is covered by a `Patch`. That **does not mean there is actual useful imaging data there**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Get table list from /Users/song/Dropbox/work/project/unagi/unagi/data/pdr2_wide/pdr2_wide_tables.fits\n"
     ]
    }
   ],
   "source": [
    "pdr2_wide = hsc.Hsc(dr='pdr2', rerun='pdr2_wide')\n",
    "\n",
    "coord_1 = SkyCoord(150.0913, 2.205916, frame='icrs', unit='deg')\n",
    "coord_2 = SkyCoord(150.1213, 40.235916, frame='icrs', unit='deg')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Covered by 5-band\n",
      "['HSC-G', 'HSC-I', 'HSC-R', 'HSC-Y', 'HSC-Z']\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<i>Table length=5</i>\n",
       "<table id=\"table4870771280\" class=\"table-striped table-bordered table-condensed\">\n",
       "<thead><tr><th>tract</th><th>patch</th><th>filter01</th></tr></thead>\n",
       "<thead><tr><th>int32</th><th>bytes64</th><th>bytes64</th></tr></thead>\n",
       "<tr><td>9813</td><td>5,4</td><td>HSC-G</td></tr>\n",
       "<tr><td>9813</td><td>5,4</td><td>HSC-I</td></tr>\n",
       "<tr><td>9813</td><td>5,4</td><td>HSC-R</td></tr>\n",
       "<tr><td>9813</td><td>5,4</td><td>HSC-Y</td></tr>\n",
       "<tr><td>9813</td><td>5,4</td><td>HSC-Z</td></tr>\n",
       "</table>"
      ],
      "text/plain": [
       "<Table length=5>\n",
       "tract  patch  filter01\n",
       "int32 bytes64 bytes64 \n",
       "----- ------- --------\n",
       " 9813     5,4    HSC-G\n",
       " 9813     5,4    HSC-I\n",
       " 9813     5,4    HSC-R\n",
       " 9813     5,4    HSC-Y\n",
       " 9813     5,4    HSC-Z"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "task.hsc_check_coverage(coord_1, archive=pdr2_wide, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Not covered\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<i>Table length=0</i>\n",
       "<table id=\"table4871907168\" class=\"table-striped table-bordered table-condensed\">\n",
       "<thead><tr><th>tract</th><th>patch</th><th>filter01</th></tr></thead>\n",
       "<thead><tr><th>int32</th><th>bytes64</th><th>bytes64</th></tr></thead>\n",
       "</table>"
      ],
      "text/plain": [
       "<Table length=0>\n",
       "tract  patch  filter01\n",
       "int32 bytes64 bytes64 \n",
       "----- ------- --------"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "task.hsc_check_coverage(coord_2, archive=pdr2_wide, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
